package com.witmore.neutron.ai.mcp.server.trading.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.witmore.neutron.ai.mcp.server.trading.dto.AlertConfig;
import com.witmore.neutron.ai.mcp.server.trading.dto.StockAnalysisResult;
import com.witmore.neutron.ai.mcp.server.trading.dto.StockRealTimeInfo;
import com.witmore.neutron.ai.mcp.server.trading.dto.StockRealTimeInfoSingleResponse;
import com.witmore.neutron.ai.mcp.server.trading.dto.StockAnalysisReportDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 异动PDF报告生成服务（使用实体类）
 *
 * @author 豆子高
 * @since 2025-01-27
 */
@Slf4j
@Service
public class AbnormalPdfReportService {

    /**
     * 生成异动报告PDF（主接口 - 实时异动场景）
     *
     * @param userId           用户ID
     * @param stockCode        股票代码
     * @param stockData        股票实时数据
     * @param analysisResult   股票分析结果
     * @param alertConfig      预警配置
     * @return PDF字节数组
     */
    public byte[] generateAbnormalReportPdf(Long userId, String stockCode,
                                           StockRealTimeInfoSingleResponse stockData,
                                           StockAnalysisResult analysisResult, AlertConfig alertConfig) throws IOException {
        log.info("开始生成异动PDF报告（实体类方式） - 用户ID: {}, 股票代码: {}", userId, stockCode);

        try {
            // 生成HTML内容
            String htmlContent = generateAbnormalReportHtmlPrivate(userId, stockCode, stockData, analysisResult, alertConfig);

            // 转换为PDF
            return convertHtmlToPdf(htmlContent);

        } catch (Exception e) {
            log.error("异动PDF报告生成失败（实体类方式） - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, stockCode, e.getMessage(), e);
            
            // 直接抛出异常，不使用简化版本回退
            throw new IOException("异动PDF报告生成失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成综合异动报告PDF（包含异动分析和完整财务分析）
     *
     * @param userId           用户ID
     * @param stockCode        股票代码
     * @param stockData        股票实时数据
     * @param analysisResult   股票分析结果
     * @param alertConfig      预警配置
     * @param financialReport  完整的财务分析报告
     * @return PDF字节数组
     */
    public byte[] generateComprehensiveAbnormalReportPdf(Long userId, String stockCode,
                                                        StockRealTimeInfoSingleResponse stockData,
                                                        StockAnalysisResult analysisResult, AlertConfig alertConfig,
                                                        StockAnalysisReportDTO financialReport) throws IOException {
        log.info("开始生成综合异动PDF报告（含财务分析） - 用户ID: {}, 股票代码: {}", userId, stockCode);

        try {
            // 生成包含异动和财务分析的HTML内容
            String htmlContent = generateComprehensiveAbnormalReportHtmlPrivate(userId, stockCode, stockData, 
                    analysisResult, alertConfig, financialReport);

            // 转换为PDF
            return convertHtmlToPdf(htmlContent);

        } catch (Exception e) {
            log.error("综合异动PDF报告生成失败 - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, stockCode, e.getMessage(), e);
            
            // 直接抛出异常，不使用简化版本回退
            throw new IOException("综合异动PDF报告生成失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成财务分析报告PDF（基于财务分析数据）
     *
     * @param userId         用户ID
     * @param analysisReport 财务分析报告数据
     * @return PDF字节数组
     */
    public byte[] generateFinancialAnalysisReportPdf(Long userId, StockAnalysisReportDTO analysisReport) throws IOException {
        log.info("开始生成财务分析PDF报告 - 用户ID: {}, 股票代码: {}", userId, analysisReport.getStockCode());

        try {
            // 生成HTML内容
            String htmlContent = generateFinancialAnalysisHtml(userId, analysisReport);

            // 转换为PDF
            return convertHtmlToPdf(htmlContent);

        } catch (Exception e) {
            log.error("财务分析PDF报告生成失败 - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, analysisReport.getStockCode(), e.getMessage(), e);
            
            // 直接抛出异常，不使用简化版本回退
            throw new IOException("财务分析PDF报告生成失败: " + e.getMessage(), e);
        }
    }

    // ==================== HTML网页生成功能 ====================

    /**
     * 生成综合异动报告HTML网页（包含异动分析和完整财务分析）
     * 主要生成方法，返回HTML字符串用于直接访问或保存为文件
     *
     * @param userId           用户ID
     * @param stockCode        股票代码
     * @param stockData        股票实时数据
     * @param analysisResult   股票分析结果
     * @param alertConfig      预警配置
     * @param financialReport  完整的财务分析报告
     * @return HTML字符串
     */
    public String generateComprehensiveAbnormalReportHtml(Long userId, String stockCode,
                                                         StockRealTimeInfoSingleResponse stockData,
                                                         StockAnalysisResult analysisResult, AlertConfig alertConfig,
                                                         StockAnalysisReportDTO financialReport) {
        log.info("开始生成综合异动HTML报告 - 用户ID: {}, 股票代码: {}", userId, stockCode);

        try {
            // 直接生成HTML内容，使用优化的网页样式
            return generateComprehensiveAbnormalReportHtmlContent(userId, stockCode, stockData, 
                    analysisResult, alertConfig, financialReport);

        } catch (Exception e) {
            log.error("综合异动HTML报告生成失败 - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, stockCode, e.getMessage(), e);
            
            // 生成错误页面
            return generateErrorHtml(userId, stockCode, e.getMessage());
        }
    }

    /**
     * 生成异动报告HTML网页（基础版本）
     *
     * @param userId           用户ID
     * @param stockCode        股票代码
     * @param stockData        股票实时数据
     * @param analysisResult   股票分析结果
     * @param alertConfig      预警配置
     * @return HTML字符串
     */
    public String generateAbnormalReportHtml(Long userId, String stockCode,
                                            StockRealTimeInfoSingleResponse stockData,
                                            StockAnalysisResult analysisResult, AlertConfig alertConfig) {
        log.info("开始生成基础异动HTML报告 - 用户ID: {}, 股票代码: {}", userId, stockCode);

        try {
            // 生成基础异动HTML内容
            return generateAbnormalReportHtmlContent(userId, stockCode, stockData, analysisResult, alertConfig);

        } catch (Exception e) {
            log.error("基础异动HTML报告生成失败 - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, stockCode, e.getMessage(), e);
            
            // 生成错误页面
            return generateErrorHtml(userId, stockCode, e.getMessage());
        }
    }

    /**
     * 生成财务分析报告HTML网页
     *
     * @param userId         用户ID
     * @param analysisReport 财务分析报告数据
     * @return HTML字符串
     */
    public String generateFinancialAnalysisReportHtml(Long userId, StockAnalysisReportDTO analysisReport) {
        log.info("开始生成财务分析HTML报告 - 用户ID: {}, 股票代码: {}", userId, analysisReport.getStockCode());

        try {
            // 生成财务分析HTML内容
            return generateFinancialAnalysisHtmlContent(userId, analysisReport);

        } catch (Exception e) {
            log.error("财务分析HTML报告生成失败 - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, analysisReport.getStockCode(), e.getMessage(), e);
            
            // 生成错误页面
            return generateErrorHtml(userId, analysisReport.getStockCode(), e.getMessage());
        }
    }

    /**
     * 生成异动报告PDF（重载方法 - 基于数据库记录）
     *
     * @param userId                用户ID
     * @param stockCode             股票代码
     * @param abnormalDataJson      异动数据JSON字符串
     * @param stockBasicInfoJson    股票基本信息JSON字符串
     * @return PDF字节数组
     */
    public byte[] generateAbnormalReportPdfFromRecord(Long userId, String stockCode,
                                                     String abnormalDataJson, String stockBasicInfoJson) throws IOException {
        log.info("开始生成异动PDF报告（基于记录） - 用户ID: {}, 股票代码: {}", userId, stockCode);

        try {
            // 解析JSON数据构造实体类
            JSONObject abnormalData = JSON.parseObject(abnormalDataJson);

            // 构造StockAnalysisResult
            StockAnalysisResult analysisResult = new StockAnalysisResult();
            analysisResult.setCurrentPrice(abnormalData.getBigDecimal("currentPrice"));
            analysisResult.setLastRecordPrice(abnormalData.getBigDecimal("lastRecordPrice"));
            analysisResult.setChangeRatio(abnormalData.getBigDecimal("changeRatio"));
            analysisResult.setStockName(abnormalData.getString("stockName"));
            analysisResult.setAbnormal(true); // 从数据库记录生成的都是异动记录
            analysisResult.setAbnormalType(abnormalData.getString("abnormalType"));
            analysisResult.setTriggerThreshold(abnormalData.getBigDecimal("triggerThreshold"));
            analysisResult.setFirstRecord(false);

            // 构造AlertConfig
            AlertConfig alertConfig = new AlertConfig();
            JSONObject alertConfigJson = abnormalData.getJSONObject("alertConfig");
            if (alertConfigJson != null) {
                alertConfig.setRiseRatio(alertConfigJson.getBigDecimal("riseRatio"));
                alertConfig.setFallRatio(alertConfigJson.getBigDecimal("fallRatio"));
                alertConfig.setPushFrequency(alertConfigJson.getInteger("pushFrequency"));
            }

            // 生成HTML内容（不需要stockData，因为信息已经在analysisResult中）
            String htmlContent = generateAbnormalReportHtmlFromRecord(userId, stockCode, analysisResult, alertConfig);

            // 转换为PDF
            return convertHtmlToPdf(htmlContent);

        } catch (Exception e) {
            log.error("异动PDF报告生成失败（基于记录） - 用户ID: {}, 股票代码: {}, 错误: {}",
                    userId, stockCode, e.getMessage(), e);
            throw new IOException("异动PDF报告生成失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成异动报告HTML内容（实时场景 - 私有方法）
     */
    private String generateAbnormalReportHtmlPrivate(Long userId, String stockCode,
                                                    StockRealTimeInfoSingleResponse stockData,
                                                    StockAnalysisResult analysisResult, AlertConfig alertConfig) {
        StringBuilder html = new StringBuilder();

        // 从股票数据中提取信息
        String stockName = extractStockName(stockData.data());
        BigDecimal currentPrice = extractCurrentPrice(stockData.data());

        // 从实体类中直接获取数据
        String abnormalType = analysisResult.getAbnormalType();
        BigDecimal changeRatio = analysisResult.getChangeRatio();
        BigDecimal lastRecordPrice = analysisResult.getLastRecordPrice();
        BigDecimal triggerThreshold = analysisResult.getTriggerThreshold();

        // 优先使用分析结果中的数据
        if (StringUtils.hasText(analysisResult.getStockName())) {
            stockName = analysisResult.getStockName();
        }
        if (analysisResult.getCurrentPrice() != null) {
            currentPrice = analysisResult.getCurrentPrice();
        }

        log.info("从实体类提取的数据 - 异动类型: {}, 涨跌幅: {}, 上次价格: {}, 触发阈值: {}",
                abnormalType, changeRatio, lastRecordPrice, triggerThreshold);

        return buildHtmlContent(userId, stockCode, stockName, currentPrice, abnormalType,
                               changeRatio, lastRecordPrice, triggerThreshold, alertConfig,
                               stockData != null ? stockData.data() : null);
    }

    /**
     * 生成异动报告HTML内容（基于记录场景）
     */
    private String generateAbnormalReportHtmlFromRecord(Long userId, String stockCode,
                                                       StockAnalysisResult analysisResult, AlertConfig alertConfig) {

        String stockName = analysisResult.getStockName();
        BigDecimal currentPrice = analysisResult.getCurrentPrice();
        String abnormalType = analysisResult.getAbnormalType();
        BigDecimal changeRatio = analysisResult.getChangeRatio();
        BigDecimal lastRecordPrice = analysisResult.getLastRecordPrice();
        BigDecimal triggerThreshold = analysisResult.getTriggerThreshold();

        log.info("从数据库记录提取的数据 - 异动类型: {}, 涨跌幅: {}, 上次价格: {}, 触发阈值: {}",
                abnormalType, changeRatio, lastRecordPrice, triggerThreshold);

        return buildHtmlContent(userId, stockCode, stockName, currentPrice, abnormalType,
                               changeRatio, lastRecordPrice, triggerThreshold, alertConfig, null);
    }

    /**
     * 生成财务分析报告HTML内容
     */
    private String generateFinancialAnalysisHtml(Long userId, StockAnalysisReportDTO analysisReport) {
        StringBuilder html = new StringBuilder();

        // HTML头部和样式
        html.append("<!DOCTYPE html>")
            .append("<html lang=\"zh-CN\">")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">")
            .append("<title>股票财务分析报告</title>")
            .append("<style>")
            .append(getFinancialAnalysisReportStyles())
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 报告标题
        html.append("<div class=\"header\">")
            .append("<h1>股票财务分析报告</h1>")
            .append("<div class=\"stock-info\">")
            .append("<span class=\"stock-code\">").append(analysisReport.getStockCode()).append("</span>");

        if (StringUtils.hasText(analysisReport.getStockName())) {
            html.append("<span class=\"stock-name\">").append(analysisReport.getStockName()).append("</span>");
        }

        html.append("</div>")
            .append("<div class=\"report-time\">分析时间: ")
            .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</div>")
            .append("</div>");

        // 核心结论概述
        html.append("<div class=\"summary-section\">")
            .append("<h2>🎯 核心结论</h2>")
            .append("<div class=\"summary-grid\">");

        if (analysisReport.getOverallScore() != null) {
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">综合评分</span>")
                .append("<span class=\"value score\">").append(analysisReport.getOverallScore()).append("/100分</span>")
                .append("</div>");
        }

        if (analysisReport.getRiskLevel() != null) {
            String riskClass = getRiskLevelClass(analysisReport.getRiskLevel());
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">风险等级</span>")
                .append("<span class=\"value ").append(riskClass).append("\">")
                .append(analysisReport.getRiskLevel()).append("级</span>")
                .append("</div>");
        }

        if (StringUtils.hasText(analysisReport.getInvestmentRecommendation())) {
            String recommendClass = getRecommendationClass(analysisReport.getInvestmentRecommendation());
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">投资建议</span>")
                .append("<span class=\"value ").append(recommendClass).append("\">")
                .append(analysisReport.getInvestmentRecommendation()).append("</span>")
                .append("</div>");
        }

        html.append("</div>");

        // 建议理由
        if (StringUtils.hasText(analysisReport.getRecommendationReason())) {
            html.append("<div class=\"recommendation-reason\">")
                .append("<h3>建议理由</h3>")
                .append("<p>").append(analysisReport.getRecommendationReason()).append("</p>")
                .append("</div>");
        }

        html.append("</div>");

        // 财务分析各个维度
        addFinancialAnalysisSection(html, "💰 综合财务分析", analysisReport.getFinancialAnalysis());
        addFinancialAnalysisSection(html, "📈 盈利能力分析", analysisReport.getProfitabilityAnalysis());
        addFinancialAnalysisSection(html, "🛡️ 偿债能力分析", analysisReport.getSolvencyAnalysis());
        addFinancialAnalysisSection(html, "⚙️ 营运能力分析", analysisReport.getOperationalAnalysis());
        addFinancialAnalysisSection(html, "🚀 成长能力分析", analysisReport.getGrowthAnalysis());
        addFinancialAnalysisSection(html, "💧 现金流分析", analysisReport.getCashFlowAnalysis());
        addFinancialAnalysisSection(html, "📊 研报分析", analysisReport.getResearchAnalysis());

        // 目标价格区间
        if (StringUtils.hasText(analysisReport.getTargetPriceRange())) {
            html.append("<div class=\"target-price-section\">")
                .append("<h2>🎯 目标价格区间</h2>")
                .append("<div class=\"target-price-content\">")
                .append(formatAnalysisContent(analysisReport.getTargetPriceRange()))
                .append("</div>")
                .append("</div>");
        }

        // AI总结
        if (StringUtils.hasText(analysisReport.getAiSummary())) {
            html.append("<div class=\"ai-summary-section\">")
                .append("<h2>🤖 AI智能总结</h2>")
                .append("<div class=\"ai-summary-content\">")
                .append(formatAnalysisContent(analysisReport.getAiSummary()))
                .append("</div>")
                .append("</div>");
        }

        // 风险提示
        html.append("<div class=\"risk-section\">")
            .append("<h2>⚠️ 风险提示</h2>")
            .append("<div class=\"risk-content\">")
            .append("<p><strong>数据来源：</strong> 本报告基于公开财务报表数据生成，数据时效性可能存在滞后。</p>")
            .append("<p><strong>分析局限：</strong> 财务分析仅基于历史数据，无法预测未来市场变化和公司表现。</p>")
            .append("<p><strong>投资风险：</strong> 股票投资存在风险，过往业绩不代表未来表现，请谨慎决策。</p>");

        if (StringUtils.hasText(analysisReport.getRiskDescription())) {
            html.append("<p><strong>风险评级说明：</strong> ").append(analysisReport.getRiskDescription()).append("</p>");
        }

        html.append("</div>")
            .append("</div>");

        // 页脚
        html.append("<div class=\"footer\">")
            .append("<p><strong>免责声明：</strong> 本财务分析报告仅供参考，不构成投资建议。投资者应基于自身情况做出独立判断。</p>")
            .append("<p>用户ID: ").append(userId).append(" | ")
            .append("报告生成时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("</p>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 生成简化版财务分析HTML
     */
    private String generateSimplifiedFinancialAnalysisHtml(Long userId, StockAnalysisReportDTO analysisReport) {
        StringBuilder html = new StringBuilder();

        html.append("<!DOCTYPE html>")
            .append("<html>")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<title>股票财务分析报告</title>")
            .append("<style>")
            .append("body { font-family: sans-serif; margin: 20px; }")
            .append("h1 { color: #2b6cb0; text-align: center; }")
            .append("table { width: 100%; border-collapse: collapse; margin: 10px 0; }")
            .append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }")
            .append("th { background-color: #f2f2f2; }")
            .append(".header { text-align: center; margin-bottom: 20px; }")
            .append(".section { margin: 20px 0; padding: 15px; background: #f9f9f9; border-radius: 5px; }")
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 标题
        html.append("<div class=\"header\">")
            .append("<h1>股票财务分析报告</h1>")
            .append("<p>股票代码: ").append(analysisReport.getStockCode()).append("</p>");

        if (StringUtils.hasText(analysisReport.getStockName())) {
            html.append("<p>股票名称: ").append(analysisReport.getStockName()).append("</p>");
        }

        html.append("<p>用户ID: ").append(userId).append("</p>")
            .append("<p>分析时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("</p>")
            .append("</div>");

        // 核心指标表格
        html.append("<h2>核心指标</h2>")
            .append("<table>")
            .append("<tr><th>指标</th><th>数值</th></tr>");

        if (analysisReport.getOverallScore() != null) {
            html.append("<tr><td>综合评分</td><td>").append(analysisReport.getOverallScore()).append("/100分</td></tr>");
        }
        if (analysisReport.getRiskLevel() != null) {
            html.append("<tr><td>风险等级</td><td>").append(analysisReport.getRiskLevel()).append("级</td></tr>");
        }
        if (StringUtils.hasText(analysisReport.getInvestmentRecommendation())) {
            html.append("<tr><td>投资建议</td><td>").append(analysisReport.getInvestmentRecommendation()).append("</td></tr>");
        }

        html.append("</table>");

        // 各个分析维度
        addSimplifiedAnalysisSection(html, "财务分析", analysisReport.getFinancialAnalysis());
        addSimplifiedAnalysisSection(html, "盈利能力分析", analysisReport.getProfitabilityAnalysis());
        addSimplifiedAnalysisSection(html, "偿债能力分析", analysisReport.getSolvencyAnalysis());
        addSimplifiedAnalysisSection(html, "营运能力分析", analysisReport.getOperationalAnalysis());
        addSimplifiedAnalysisSection(html, "成长能力分析", analysisReport.getGrowthAnalysis());
        addSimplifiedAnalysisSection(html, "现金流分析", analysisReport.getCashFlowAnalysis());

        // 免责声明
        html.append("<div style=\"margin-top: 30px; padding: 10px; background: #f9f9f9; border-radius: 5px;\">")
            .append("<p><strong>免责声明：</strong> 本报告仅供参考，不构成投资建议。</p>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 构建HTML内容（统一方法）
     */
    private String buildHtmlContent(Long userId, String stockCode, String stockName,
                                   BigDecimal currentPrice, String abnormalType, BigDecimal changeRatio,
                                   BigDecimal lastRecordPrice, BigDecimal triggerThreshold,
                                   AlertConfig alertConfig, List<StockRealTimeInfo> stockDataList) {
        StringBuilder html = new StringBuilder();

        // HTML头部和样式
        html.append("<!DOCTYPE html>")
            .append("<html lang=\"zh-CN\">")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">")
            .append("<title>股票异动分析报告</title>")
            .append("<style>")
            .append(getAbnormalReportStyles())
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 报告标题
        html.append("<div class=\"header\">")
            .append("<h1>股票异动分析报告</h1>")
            .append("<div class=\"stock-info\">")
            .append("<span class=\"stock-code\">").append(stockCode).append("</span>");

        if (StringUtils.hasText(stockName)) {
            html.append("<span class=\"stock-name\">").append(stockName).append("</span>");
        }

        html.append("</div>")
            .append("<div class=\"report-time\">报告时间: ")
            .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</div>")
            .append("</div>");

        // 异动概述
        html.append("<div class=\"summary-section\">")
            .append("<h2>📊 异动概述</h2>")
            .append("<div class=\"summary-grid\">");

        // 异动类型
        if (StringUtils.hasText(abnormalType)) {
            String typeClass = getAbnormalTypeClass(abnormalType);
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">异动类型</span>")
                .append("<span class=\"value ").append(typeClass).append("\">")
                .append(abnormalType).append("</span>")
                .append("</div>");
        }

        // 当前价格
        if (currentPrice != null) {
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">当前价格</span>")
                .append("<span class=\"value price\">¥").append(currentPrice).append("</span>")
                .append("</div>");
        }

        // 涨跌幅
        if (changeRatio != null) {
            String ratioClass = changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative";
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">涨跌幅</span>")
                .append("<span class=\"value ").append(ratioClass).append("\">")
                .append(changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "")
                .append(changeRatio).append("%</span>")
                .append("</div>");
        }

        // 触发阈值
        if (triggerThreshold != null) {
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">触发阈值</span>")
                .append("<span class=\"value threshold\">").append(triggerThreshold).append("%</span>")
                .append("</div>");
        }

        html.append("</div>")
            .append("</div>");

        // 价格变化详情
        html.append("<div class=\"price-detail-section\">")
            .append("<h2>💰 价格变化详情</h2>")
            .append("<div class=\"price-table\">")
            .append("<table>")
            .append("<tr><th>项目</th><th>数值</th></tr>");

        if (lastRecordPrice != null) {
            html.append("<tr><td>上次记录价格</td><td>¥").append(lastRecordPrice).append("</td></tr>");
        }
        if (currentPrice != null) {
            html.append("<tr><td>当前价格</td><td>¥").append(currentPrice).append("</td></tr>");
        }
        if (changeRatio != null) {
            String changeText = changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "上涨" : "下跌";
            html.append("<tr><td>价格变化</td><td class=\"")
                .append(changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative")
                .append("\">").append(changeText).append(" ").append(changeRatio.abs()).append("%</td></tr>");
        }

        html.append("</table>")
            .append("</div>")
            .append("</div>");

        // 预警配置信息
        if (alertConfig != null) {
            html.append("<div class=\"alert-config-section\">")
                .append("<h2>⚙️ 预警配置</h2>")
                .append("<div class=\"config-content\">")
                .append(formatAlertConfig(alertConfig))
                .append("</div>")
                .append("</div>");
        }

        // 股票详细信息（如果有的话）
        if (stockDataList != null && !stockDataList.isEmpty()) {
            html.append("<div class=\"stock-detail-section\">")
                .append("<h2>📈 股票详细信息</h2>")
                .append("<div class=\"stock-table\">")
                .append(formatStockData(stockDataList))
                .append("</div>")
                .append("</div>");
        }

        // 风险提示
        html.append("<div class=\"risk-section\">")
            .append("<h2>⚠️ 风险提示</h2>")
            .append("<div class=\"risk-content\">")
            .append("<p><strong>异动说明：</strong> 股票价格变化超过预设阈值，触发异动预警。</p>")
            .append("<p><strong>投资风险：</strong> 股价异动可能由多种因素引起，投资者应谨慎决策。</p>")
            .append("<p><strong>数据来源：</strong> 本报告基于实时股票数据生成，仅供参考。</p>")
            .append("</div>")
            .append("</div>");

        // 页脚
        html.append("<div class=\"footer\">")
            .append("<p><strong>免责声明：</strong> 本异动分析报告仅供参考，不构成投资建议。投资者应基于自身情况做出独立判断。</p>")
            .append("<p>用户ID: ").append(userId).append(" | ")
            .append("报告生成时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("</p>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 从股票数据中提取股票名称
     */
    private String extractStockName(List<StockRealTimeInfo> stockDataList) {
        if (stockDataList == null) return null;

        for (StockRealTimeInfo info : stockDataList) {
            if ("股票简称".equals(info.item())) {
                return info.value();
            }
        }
        return null;
    }

    /**
     * 从股票数据中提取当前价格
     */
    private BigDecimal extractCurrentPrice(List<StockRealTimeInfo> stockDataList) {
        if (stockDataList == null) return null;

        for (StockRealTimeInfo info : stockDataList) {
            if ("最新".equals(info.item())) {
                try {
                    return new BigDecimal(info.value());
                } catch (NumberFormatException e) {
                    log.warn("解析当前价格失败: {}", info.value());
                }
            }
        }
        return null;
    }

    /**
     * 格式化预警配置
     */
    private String formatAlertConfig(AlertConfig alertConfig) {
        StringBuilder config = new StringBuilder();

        config.append("<table>")
              .append("<tr><th>配置项</th><th>数值</th></tr>");

        BigDecimal riseRatio = alertConfig.getRiseRatio();
        BigDecimal fallRatio = alertConfig.getFallRatio();
        Integer pushFrequency = alertConfig.getPushFrequency();

        if (riseRatio != null) {
            config.append("<tr><td>上涨预警阈值</td><td>").append(riseRatio).append("%</td></tr>");
        }
        if (fallRatio != null) {
            config.append("<tr><td>下跌预警阈值</td><td>").append(fallRatio).append("%</td></tr>");
        }
        if (pushFrequency != null) {
            config.append("<tr><td>推送频率</td><td>").append(pushFrequency).append("</td></tr>");
        }

        config.append("</table>");

        return config.toString();
    }

    /**
     * 格式化股票数据
     */
    private String formatStockData(List<StockRealTimeInfo> stockDataList) {
        StringBuilder table = new StringBuilder();
        table.append("<table>")
             .append("<tr><th>项目</th><th>数值</th></tr>");

        for (StockRealTimeInfo info : stockDataList) {
            table.append("<tr>")
                 .append("<td>").append(info.item()).append("</td>")
                 .append("<td>").append(info.value()).append("</td>")
                 .append("</tr>");
        }

        table.append("</table>");
        return table.toString();
    }

    /**
     * 获取异动类型样式类
     */
    private String getAbnormalTypeClass(String abnormalType) {
        if (abnormalType.contains("上涨")) return "type-rise";
        if (abnormalType.contains("下跌")) return "type-fall";
        return "type-normal";
    }

    /**
     * 获取风险等级样式类
     */
    private String getRiskLevelClass(Integer riskLevel) {
        if (riskLevel == null) return "risk-unknown";
        if (riskLevel <= 2) return "risk-low";
        if (riskLevel <= 3) return "risk-medium";
        return "risk-high";
    }

    /**
     * 获取投资建议样式类
     */
    private String getRecommendationClass(String recommendation) {
        if (recommendation.contains("买入")) return "recommend-buy";
        if (recommendation.contains("卖出")) return "recommend-sell";
        if (recommendation.contains("持有")) return "recommend-hold";
        return "recommend-neutral";
    }

    /**
     * 添加财务分析维度章节
     */
    private void addFinancialAnalysisSection(StringBuilder html, String title, String content) {
        if (StringUtils.hasText(content)) {
            html.append("<div class=\"analysis-section\">")
                .append("<h2>").append(title).append("</h2>")
                .append("<div class=\"analysis-content\">")
                .append(formatAnalysisContent(content))
                .append("</div>")
                .append("</div>");
        }
    }

    /**
     * 添加简化版分析章节
     */
    private void addSimplifiedAnalysisSection(StringBuilder html, String title, String content) {
        if (StringUtils.hasText(content)) {
            html.append("<div class=\"section\">")
                .append("<h3>").append(title).append("</h3>")
                .append("<p>").append(formatSimpleAnalysisContent(content)).append("</p>")
                .append("</div>");
        }
    }

    /**
     * 格式化分析内容（保持原有的markdown格式并转换为HTML）
     */
    private String formatAnalysisContent(String content) {
        if (!StringUtils.hasText(content)) {
            return "";
        }

        // 简单的markdown到HTML转换
        return content
            .replaceAll("\\*\\*([^*]+)\\*\\*", "<strong>$1</strong>") // 粗体
            .replaceAll("\\*([^*]+)\\*", "<em>$1</em>") // 斜体
            .replaceAll("\\n\\n", "</p><p>") // 段落分隔
            .replaceAll("\\n", "<br/>") // 换行
            .replaceAll("^", "<p>") // 开始段落
            .replaceAll("$", "</p>"); // 结束段落
    }

    /**
     * 格式化简单分析内容（去除格式化字符）
     */
    private String formatSimpleAnalysisContent(String content) {
        if (!StringUtils.hasText(content)) {
            return "";
        }

        // 移除markdown格式字符，保留纯文本
        return content
            .replaceAll("\\*\\*([^*]+)\\*\\*", "$1") // 移除粗体标记
            .replaceAll("\\*([^*]+)\\*", "$1") // 移除斜体标记
            .replaceAll("\\n+", " ") // 将换行符替换为空格
            .trim();
    }

    /**
     * HTML转PDF
     * 使用最基础的字体配置，避免cmap null错误
     */
    private byte[] convertHtmlToPdf(String htmlContent) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        try {
            // 配置转换属性 - 使用最简单最安全的配置
            ConverterProperties properties = new ConverterProperties();

            // 使用最基础的字体提供器，不添加任何外部字体
            DefaultFontProvider fontProvider = new DefaultFontProvider();
            
            // 只添加iText内置的标准字体，绝对安全
            fontProvider.addStandardPdfFonts();
            
            properties.setFontProvider(fontProvider);
            properties.setCharset("UTF-8");

            log.info("使用安全字体配置开始HTML转PDF转换，HTML长度: {} 字符", htmlContent.length());

            HtmlConverter.convertToPdf(htmlContent, outputStream, properties);

            log.info("PDF转换成功 - 文件大小: {} bytes", outputStream.size());

            return outputStream.toByteArray();

        } catch (Exception e) {
            log.error("HTML转PDF失败，错误详情: {}", e.getMessage(), e);
            
            // 如果还是失败，尝试最极简的字体配置
            try {
                log.info("尝试使用最极简字体配置重新转换PDF");
                return convertWithMinimalConfig(htmlContent);
            } catch (Exception fallbackE) {
                log.error("极简配置也失败: {}", fallbackE.getMessage());
                throw new IOException("PDF转换完全失败: " + e.getMessage() + 
                    " (极简配置失败: " + fallbackE.getMessage() + ")", e);
            }
            
        } finally {
            try {
                outputStream.close();
            } catch (Exception e) {
                log.warn("关闭输出流失败: {}", e.getMessage());
            }
        }
    }

    /**
     * 使用最极简配置转换PDF
     */
    private byte[] convertWithMinimalConfig(String htmlContent) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        
        try {
            // 生成极简版本的HTML，移除所有可能导致字体问题的元素
            String simplifiedHtml = createFontSafeHtml(htmlContent);
            
            // 最极简的配置，不设置任何字体提供器
            ConverterProperties properties = new ConverterProperties();
            properties.setCharset("UTF-8");
            
            log.info("使用字体安全HTML和极简配置转换PDF");
            HtmlConverter.convertToPdf(simplifiedHtml, outputStream, properties);
            
            log.info("极简配置PDF转换成功 - 文件大小: {} bytes", outputStream.size());
            return outputStream.toByteArray();
            
        } finally {
            try {
                outputStream.close();
            } catch (Exception e) {
                log.warn("关闭极简配置输出流失败: {}", e.getMessage());
            }
        }
    }

    /**
     * 创建字体安全的HTML，移除所有可能导致字体问题的元素
     */
    private String createFontSafeHtml(String originalHtml) {
        // 提取基本内容，重新生成最安全的HTML
        String template = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <title>股票分析报告</title>
                <style>
                    body { 
                        margin: 20px; 
                        line-height: 1.5;
                        color: black;
                    }
                    h1 { 
                        text-align: center; 
                        color: #d32f2f;
                        margin-bottom: 20px;
                    }
                    h2 { 
                        color: #1976d2; 
                        border-bottom: 2px solid #1976d2; 
                        padding-bottom: 5px;
                        margin-top: 25px;
                        margin-bottom: 15px;
                    }
                    table { 
                        width: 100%; 
                        border-collapse: collapse; 
                        margin: 15px 0; 
                    }
                    th, td { 
                        border: 1px solid #ddd; 
                        padding: 8px; 
                        text-align: left; 
                    }
                    th { 
                        background-color: #f5f5f5; 
                        font-weight: bold;
                    }
                    .positive { color: #388e3c; font-weight: bold; }
                    .negative { color: #d32f2f; font-weight: bold; }
                    .section {
                        margin: 20px 0;
                        padding: 15px;
                        background: #fafafa;
                        border: 1px solid #e0e0e0;
                    }
                    .footer {
                        margin-top: 30px;
                        padding: 15px;
                        background: #f5f5f5;
                        border-top: 2px solid #ddd;
                        text-align: center;
                        font-size: 12px;
                    }
                </style>
            </head>
            <body>
                <h1>股票异动分析报告</h1>
                <div class="section">
                    <p><strong>报告说明：</strong> 由于字体配置问题，此为简化版报告。</p>
                    <p><strong>生成时间：</strong> %s</p>
                    <p><strong>状态：</strong> 系统正在优化字体配置以提供完整报告。</p>
                </div>
                <div class="footer">
                    <p><strong>免责声明：</strong> 本报告仅供参考，不构成投资建议。</p>
                </div>
            </body>
            </html>
            """;
        
        return String.format(template, 
            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }







    /**
     * 获取异动报告样式（优化版，避免字体映射错误）
     */
    private String getAbnormalReportStyles() {
        return """
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            
            body {
                font-family: sans-serif;
                line-height: 1.6;
                color: #333;
                background-color: #fff;
                padding: 20px;
                font-size: 14px;
            }
            
            .header {
                text-align: center;
                margin-bottom: 30px;
                padding-bottom: 20px;
                border-bottom: 3px solid #e53e3e;
            }
            
            .header h1 {
                color: #e53e3e;
                font-size: 28px;
                margin-bottom: 10px;
            }
            
            .stock-info {
                margin: 10px 0;
            }
            
            .stock-code {
                font-size: 20px;
                font-weight: bold;
                color: #e53e3e;
                margin-right: 10px;
            }
            
            .stock-name {
                font-size: 18px;
                color: #2d3748;
            }
            
            .report-time {
                color: #718096;
                font-size: 14px;
            }
            
            .summary-section {
                background: linear-gradient(135deg, #e53e3e 0%, #fc8181 100%);
                color: white;
                padding: 25px;
                border-radius: 10px;
                margin-bottom: 30px;
            }
            
            .summary-section h2 {
                margin-bottom: 20px;
                font-size: 22px;
                text-align: center;
            }
            
            .summary-grid {
                display: flex;
                flex-wrap: wrap;
                gap: 20px;
                justify-content: space-around;
            }
            
            .summary-item {
                text-align: center;
                flex: 1;
                min-width: 150px;
            }
            
            .summary-item .label {
                display: block;
                font-size: 14px;
                opacity: 0.9;
                margin-bottom: 8px;
            }
            
            .summary-item .value {
                display: block;
                font-size: 18px;
                font-weight: bold;
            }
            
            .price-detail-section, .alert-config-section, .stock-detail-section {
                margin-bottom: 30px;
                padding: 20px;
                border: 1px solid #e2e8f0;
                border-radius: 8px;
                background: #f7fafc;
            }
            
            .price-detail-section h2, .alert-config-section h2, .stock-detail-section h2 {
                color: #2d3748;
                font-size: 20px;
                margin-bottom: 15px;
                border-bottom: 2px solid #4299e1;
                padding-bottom: 5px;
            }
            
            table {
                width: 100%;
                border-collapse: collapse;
                margin-top: 10px;
            }
            
            th, td {
                border: 1px solid #e2e8f0;
                padding: 12px;
                text-align: left;
            }
            
            th {
                background-color: #edf2f7;
                font-weight: bold;
                color: #2d3748;
            }
            
            tr:nth-child(even) {
                background-color: #f7fafc;
            }
            
            .positive {
                color: #38a169 !important;
                font-weight: bold;
            }
            
            .negative {
                color: #e53e3e !important;
                font-weight: bold;
            }
            
            .price {
                color: #3182ce;
                font-weight: bold;
            }
            
            .threshold {
                color: #d69e2e;
                font-weight: bold;
            }
            
            .type-rise {
                color: #38a169;
                background: rgba(56, 161, 105, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .type-fall {
                color: #e53e3e;
                background: rgba(229, 62, 62, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .type-normal {
                color: #3182ce;
                background: rgba(49, 130, 206, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .risk-section {
                background: #fed7d7;
                border: 1px solid #feb2b2;
                border-radius: 8px;
                padding: 20px;
                margin-bottom: 30px;
            }
            
            .risk-section h2 {
                color: #c53030;
                margin-bottom: 15px;
            }
            
            .risk-content {
                color: #742a2a;
            }
            
            .risk-content p {
                margin-bottom: 10px;
            }
            
            .footer {
                margin-top: 40px;
                padding-top: 20px;
                border-top: 1px solid #e2e8f0;
                text-align: center;
                color: #718096;
                font-size: 12px;
            }
            
            .footer p {
                margin-bottom: 5px;
            }
            
            @media print {
                body { 
                    padding: 10px; 
                    font-size: 12px;
                }
                .summary-section { 
                    background: #f0f0f0 !important; 
                    color: #333 !important; 
                }
                .header h1 {
                    font-size: 24px;
                }
                h2 {
                    font-size: 18px;
                }
            }
            """;
    }

    /**
     * 获取财务分析报告样式（优化版，避免字体映射错误）
     */
    private String getFinancialAnalysisReportStyles() {
        return """
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            
            body {
                font-family: sans-serif;
                line-height: 1.6;
                color: #333;
                background-color: #fff;
                padding: 20px;
                font-size: 14px;
            }
            
            .header {
                text-align: center;
                margin-bottom: 30px;
                padding-bottom: 20px;
                border-bottom: 3px solid #2b6cb0;
            }
            
            .header h1 {
                color: #2b6cb0;
                font-size: 28px;
                margin-bottom: 10px;
            }
            
            .stock-info {
                margin: 10px 0;
            }
            
            .stock-code {
                font-size: 20px;
                font-weight: bold;
                color: #2b6cb0;
                margin-right: 10px;
            }
            
            .stock-name {
                font-size: 18px;
                color: #2d3748;
            }
            
            .report-time {
                color: #718096;
                font-size: 14px;
            }
            
            .summary-section {
                background: linear-gradient(135deg, #2b6cb0 0%, #4299e1 100%);
                color: white;
                padding: 25px;
                border-radius: 10px;
                margin-bottom: 30px;
            }
            
            .summary-section h2 {
                margin-bottom: 20px;
                font-size: 22px;
                text-align: center;
            }
            
            .summary-grid {
                display: flex;
                flex-wrap: wrap;
                gap: 20px;
                justify-content: space-around;
            }
            
            .summary-item {
                text-align: center;
                flex: 1;
                min-width: 150px;
            }
            
            .summary-item .label {
                display: block;
                font-size: 14px;
                opacity: 0.9;
                margin-bottom: 8px;
            }
            
            .summary-item .value {
                display: block;
                font-size: 18px;
                font-weight: bold;
            }
            
            .score {
                color: #ffd700 !important;
            }
            
            .risk-low {
                color: #48bb78 !important;
            }
            
            .risk-medium {
                color: #ed8936 !important;
            }
            
            .risk-high {
                color: #f56565 !important;
            }
            
            .risk-unknown {
                color: #a0aec0 !important;
            }
            
            .recommend-buy {
                color: #48bb78 !important;
                background: rgba(72, 187, 120, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .recommend-sell {
                color: #f56565 !important;
                background: rgba(245, 101, 101, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .recommend-hold {
                color: #ed8936 !important;
                background: rgba(237, 137, 54, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .recommend-neutral {
                color: #4299e1 !important;
                background: rgba(66, 153, 225, 0.1);
                padding: 4px 8px;
                border-radius: 4px;
            }
            
            .recommendation-reason {
                margin-top: 20px;
                padding: 15px;
                background: rgba(255, 255, 255, 0.1);
                border-radius: 8px;
            }
            
            .recommendation-reason h3 {
                margin-bottom: 10px;
                font-size: 16px;
            }
            
            .analysis-section {
                margin-bottom: 30px;
                padding: 20px;
                border: 1px solid #e2e8f0;
                border-radius: 8px;
                background: #f7fafc;
            }
            
            .analysis-section h2 {
                color: #2d3748;
                font-size: 20px;
                margin-bottom: 15px;
                border-bottom: 2px solid #4299e1;
                padding-bottom: 5px;
            }
            
            .analysis-content {
                color: #4a5568;
                line-height: 1.8;
            }
            
            .analysis-content p {
                margin-bottom: 12px;
            }
            
            .analysis-content strong {
                color: #2d3748;
                font-weight: 600;
            }
            
            .analysis-content em {
                color: #4299e1;
                font-style: normal;
                font-weight: 500;
            }
            
            .target-price-section, .ai-summary-section {
                margin-bottom: 30px;
                padding: 20px;
                border: 1px solid #bee3f8;
                border-radius: 8px;
                background: #ebf8ff;
            }
            
            .target-price-section h2, .ai-summary-section h2 {
                color: #2b6cb0;
                font-size: 20px;
                margin-bottom: 15px;
                border-bottom: 2px solid #4299e1;
                padding-bottom: 5px;
            }
            
            .target-price-content, .ai-summary-content {
                color: #2d3748;
                line-height: 1.8;
            }
            
            .risk-section {
                background: #fed7d7;
                border: 1px solid #feb2b2;
                border-radius: 8px;
                padding: 20px;
                margin-bottom: 30px;
            }
            
            .risk-section h2 {
                color: #c53030;
                margin-bottom: 15px;
            }
            
            .risk-content {
                color: #742a2a;
            }
            
            .risk-content p {
                margin-bottom: 10px;
            }
            
            .footer {
                margin-top: 40px;
                padding-top: 20px;
                border-top: 1px solid #e2e8f0;
                text-align: center;
                color: #718096;
                font-size: 12px;
            }
            
            .footer p {
                margin-bottom: 5px;
            }
            
            @media print {
                body { 
                    padding: 10px; 
                    font-size: 12px;
                }
                .summary-section { 
                    background: #f0f0f0 !important; 
                    color: #333 !important; 
                }
                .header h1 {
                    font-size: 24px;
                }
                h2 {
                    font-size: 18px;
                }
            }
            """;
    }

    /**
     * 生成综合异动报告HTML内容（包含异动分析和财务分析 - 私有方法）
     */
    private String generateComprehensiveAbnormalReportHtmlPrivate(Long userId, String stockCode,
                                                                 StockRealTimeInfoSingleResponse stockData,
                                                                 StockAnalysisResult analysisResult, AlertConfig alertConfig,
                                                                 StockAnalysisReportDTO financialReport) {
        StringBuilder html = new StringBuilder();

        // 从股票数据中提取信息
        String stockName = extractStockName(stockData.data());
        BigDecimal currentPrice = extractCurrentPrice(stockData.data());

        // 从实体类中直接获取数据
        String abnormalType = analysisResult.getAbnormalType();
        BigDecimal changeRatio = analysisResult.getChangeRatio();
        BigDecimal lastRecordPrice = analysisResult.getLastRecordPrice();
        BigDecimal triggerThreshold = analysisResult.getTriggerThreshold();

        // 优先使用分析结果中的数据
        if (StringUtils.hasText(analysisResult.getStockName())) {
            stockName = analysisResult.getStockName();
        }
        if (analysisResult.getCurrentPrice() != null) {
            currentPrice = analysisResult.getCurrentPrice();
        }

        // 如果财务报告中有股票名称，优先使用
        if (financialReport != null && StringUtils.hasText(financialReport.getStockName())) {
            stockName = financialReport.getStockName();
        }

        // HTML头部和样式
        html.append("<!DOCTYPE html>")
            .append("<html lang=\"zh-CN\">")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">")
            .append("<title>股票异动综合分析报告</title>")
            .append("<style>")
            .append(getComprehensiveReportStyles())
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 报告标题
        html.append("<div class=\"header\">")
            .append("<h1>股票异动综合分析报告</h1>")
            .append("<div class=\"stock-info\">")
            .append("<span class=\"stock-code\">").append(stockCode).append("</span>");

        if (StringUtils.hasText(stockName)) {
            html.append("<span class=\"stock-name\">").append(stockName).append("</span>");
        }

        html.append("</div>")
            .append("<div class=\"report-time\">报告时间: ")
            .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</div>")
            .append("</div>");

        // 第一部分：异动概述
        html.append("<div class=\"section abnormal-section\">")
            .append("<h2>🚨 异动概述</h2>")
            .append("<div class=\"summary-grid\">");

        // 异动类型
        if (StringUtils.hasText(abnormalType)) {
            String typeClass = getAbnormalTypeClass(abnormalType);
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">异动类型</span>")
                .append("<span class=\"value ").append(typeClass).append("\">")
                .append(abnormalType).append("</span>")
                .append("</div>");
        }

        // 当前价格
        if (currentPrice != null) {
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">当前价格</span>")
                .append("<span class=\"value price\">¥").append(currentPrice).append("</span>")
                .append("</div>");
        }

        // 涨跌幅
        if (changeRatio != null) {
            String ratioClass = changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative";
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">涨跌幅</span>")
                .append("<span class=\"value ").append(ratioClass).append("\">")
                .append(changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "")
                .append(changeRatio).append("%</span>")
                .append("</div>");
        }

        // 触发阈值
        if (triggerThreshold != null) {
            html.append("<div class=\"summary-item\">")
                .append("<span class=\"label\">触发阈值</span>")
                .append("<span class=\"value threshold\">").append(triggerThreshold).append("%</span>")
                .append("</div>");
        }

        html.append("</div>")
            .append("</div>");

        // 第二部分：财务分析概览（如果有的话）
        if (financialReport != null) {
            html.append("<div class=\"section financial-overview-section\">")
                .append("<h2>📊 财务健康度概览</h2>")
                .append("<div class=\"summary-grid\">");

            if (financialReport.getOverallScore() != null) {
                html.append("<div class=\"summary-item\">")
                    .append("<span class=\"label\">综合评分</span>")
                    .append("<span class=\"value score\">").append(financialReport.getOverallScore()).append("/100分</span>")
                    .append("</div>");
            }

            if (financialReport.getRiskLevel() != null) {
                String riskClass = getRiskLevelClass(financialReport.getRiskLevel());
                html.append("<div class=\"summary-item\">")
                    .append("<span class=\"label\">风险等级</span>")
                    .append("<span class=\"value ").append(riskClass).append("\">")
                    .append(financialReport.getRiskLevel()).append("级</span>")
                    .append("</div>");
            }

            if (StringUtils.hasText(financialReport.getInvestmentRecommendation())) {
                String recommendClass = getRecommendationClass(financialReport.getInvestmentRecommendation());
                html.append("<div class=\"summary-item\">")
                    .append("<span class=\"label\">投资建议</span>")
                    .append("<span class=\"value ").append(recommendClass).append("\">")
                    .append(financialReport.getInvestmentRecommendation()).append("</span>")
                    .append("</div>");
            }

            html.append("</div>");

            // 建议理由
            if (StringUtils.hasText(financialReport.getRecommendationReason())) {
                html.append("<div class=\"recommendation-reason\">")
                    .append("<h3>投资建议理由</h3>")
                    .append("<p>").append(financialReport.getRecommendationReason()).append("</p>")
                    .append("</div>");
            }

            html.append("</div>");

            // 第三部分：详细财务分析
            addFinancialAnalysisSection(html, "💰 综合财务分析", financialReport.getFinancialAnalysis());
            addFinancialAnalysisSection(html, "📈 盈利能力分析", financialReport.getProfitabilityAnalysis());
            addFinancialAnalysisSection(html, "🛡️ 偿债能力分析", financialReport.getSolvencyAnalysis());
            addFinancialAnalysisSection(html, "⚙️ 营运能力分析", financialReport.getOperationalAnalysis());
            addFinancialAnalysisSection(html, "🚀 成长能力分析", financialReport.getGrowthAnalysis());
            addFinancialAnalysisSection(html, "💧 现金流分析", financialReport.getCashFlowAnalysis());
            addFinancialAnalysisSection(html, "📊 研报分析", financialReport.getResearchAnalysis());

            // AI总结
            if (StringUtils.hasText(financialReport.getAiSummary())) {
                html.append("<div class=\"ai-summary-section\">")
                    .append("<h2>🤖 AI智能总结</h2>")
                    .append("<div class=\"ai-summary-content\">")
                    .append(formatAnalysisContent(financialReport.getAiSummary()))
                    .append("</div>")
                    .append("</div>");
            }
        }

        // 第四部分：异动详情
        html.append("<div class=\"section abnormal-detail-section\">")
            .append("<h2>💰 异动价格详情</h2>")
            .append("<div class=\"price-table\">")
            .append("<table>")
            .append("<tr><th>项目</th><th>数值</th></tr>");

        if (lastRecordPrice != null) {
            html.append("<tr><td>上次记录价格</td><td>¥").append(lastRecordPrice).append("</td></tr>");
        }
        if (currentPrice != null) {
            html.append("<tr><td>当前价格</td><td>¥").append(currentPrice).append("</td></tr>");
        }
        if (changeRatio != null) {
            String changeText = changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "上涨" : "下跌";
            html.append("<tr><td>价格变化</td><td class=\"")
                .append(changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative")
                .append("\">").append(changeText).append(" ").append(changeRatio.abs()).append("%</td></tr>");
        }

        html.append("</table>")
            .append("</div>")
            .append("</div>");

        // 第五部分：预警配置信息
        if (alertConfig != null) {
            html.append("<div class=\"section alert-config-section\">")
                .append("<h2>⚙️ 预警配置</h2>")
                .append("<div class=\"config-content\">")
                .append(formatAlertConfig(alertConfig))
                .append("</div>")
                .append("</div>");
        }

        // 第六部分：股票详细信息（如果有的话）
        if (stockData != null && stockData.data() != null && !stockData.data().isEmpty()) {
            html.append("<div class=\"section stock-detail-section\">")
                .append("<h2>📈 股票详细信息</h2>")
                .append("<div class=\"stock-table\">")
                .append(formatStockData(stockData.data()))
                .append("</div>")
                .append("</div>");
        }

        // 风险提示
        html.append("<div class=\"risk-section\">")
            .append("<h2>⚠️ 风险提示</h2>")
            .append("<div class=\"risk-content\">")
            .append("<p><strong>异动说明：</strong> 股票价格变化超过预设阈值，触发异动预警。</p>")
            .append("<p><strong>财务分析：</strong> 本报告结合了实时异动监测和深度财务分析，提供全面的投资参考。</p>")
            .append("<p><strong>投资风险：</strong> 股价异动可能由多种因素引起，财务数据具有滞后性，投资者应谨慎决策。</p>")
            .append("<p><strong>数据来源：</strong> 本报告基于实时股票数据和公开财务报表数据生成，仅供参考。</p>");

        if (financialReport != null && StringUtils.hasText(financialReport.getRiskDescription())) {
            html.append("<p><strong>风险评级说明：</strong> ").append(financialReport.getRiskDescription()).append("</p>");
        }

        html.append("</div>")
            .append("</div>");

        // 页脚
        html.append("<div class=\"footer\">")
            .append("<p><strong>免责声明：</strong> 本综合分析报告仅供参考，不构成投资建议。投资者应基于自身情况做出独立判断。</p>")
            .append("<p>用户ID: ").append(userId).append(" | ")
            .append("报告生成时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("</p>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 生成简化版综合报告HTML
     */
    private String generateSimplifiedComprehensiveHtml(Long userId, String stockCode, 
                                                      StockAnalysisResult analysisResult, 
                                                      StockAnalysisReportDTO financialReport) {
        StringBuilder html = new StringBuilder();

        html.append("<!DOCTYPE html>")
            .append("<html>")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<title>股票异动综合分析报告</title>")
            .append("<style>")
            .append("body { font-family: sans-serif; margin: 20px; }")
            .append("h1 { color: #e53e3e; text-align: center; }")
            .append("h2 { color: #2b6cb0; border-bottom: 2px solid #4299e1; padding-bottom: 5px; }")
            .append("table { width: 100%; border-collapse: collapse; margin: 10px 0; }")
            .append("th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }")
            .append("th { background-color: #f2f2f2; }")
            .append(".header { text-align: center; margin-bottom: 20px; }")
            .append(".section { margin: 20px 0; padding: 15px; background: #f9f9f9; border-radius: 5px; }")
            .append(".positive { color: #38a169; font-weight: bold; }")
            .append(".negative { color: #e53e3e; font-weight: bold; }")
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 标题
        html.append("<div class=\"header\">")
            .append("<h1>股票异动综合分析报告</h1>")
            .append("<p>股票代码: ").append(stockCode).append("</p>")
            .append("<p>用户ID: ").append(userId).append("</p>")
            .append("<p>分析时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))).append("</p>")
            .append("</div>");

        // 异动信息
        html.append("<div class=\"section\">")
            .append("<h2>异动信息</h2>")
            .append("<table>")
            .append("<tr><th>项目</th><th>数值</th></tr>");

        if (analysisResult != null) {
            if (StringUtils.hasText(analysisResult.getAbnormalType())) {
                html.append("<tr><td>异动类型</td><td>").append(analysisResult.getAbnormalType()).append("</td></tr>");
            }
            if (analysisResult.getCurrentPrice() != null) {
                html.append("<tr><td>当前价格</td><td>¥").append(analysisResult.getCurrentPrice()).append("</td></tr>");
            }
            if (analysisResult.getChangeRatio() != null) {
                String changeClass = analysisResult.getChangeRatio().compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative";
                html.append("<tr><td>涨跌幅</td><td class=\"").append(changeClass).append("\">")
                    .append(analysisResult.getChangeRatio()).append("%</td></tr>");
            }
        }

        html.append("</table>")
            .append("</div>");

        // 财务分析信息
        if (financialReport != null) {
            html.append("<div class=\"section\">")
                .append("<h2>财务分析概况</h2>")
                .append("<table>")
                .append("<tr><th>指标</th><th>数值</th></tr>");

            if (financialReport.getOverallScore() != null) {
                html.append("<tr><td>综合评分</td><td>").append(financialReport.getOverallScore()).append("/100分</td></tr>");
            }
            if (financialReport.getRiskLevel() != null) {
                html.append("<tr><td>风险等级</td><td>").append(financialReport.getRiskLevel()).append("级</td></tr>");
            }
            if (StringUtils.hasText(financialReport.getInvestmentRecommendation())) {
                html.append("<tr><td>投资建议</td><td>").append(financialReport.getInvestmentRecommendation()).append("</td></tr>");
            }

            html.append("</table>");

            // 关键财务分析内容
            addSimplifiedAnalysisSection(html, "盈利能力分析", financialReport.getProfitabilityAnalysis());
            addSimplifiedAnalysisSection(html, "偿债能力分析", financialReport.getSolvencyAnalysis());
            addSimplifiedAnalysisSection(html, "营运能力分析", financialReport.getOperationalAnalysis());
            addSimplifiedAnalysisSection(html, "成长能力分析", financialReport.getGrowthAnalysis());
            addSimplifiedAnalysisSection(html, "现金流分析", financialReport.getCashFlowAnalysis());

            html.append("</div>");
        }

        // 免责声明
        html.append("<div style=\"margin-top: 30px; padding: 10px; background: #f9f9f9; border-radius: 5px;\">")
            .append("<p><strong>免责声明：</strong> 本综合报告仅供参考，不构成投资建议。</p>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 获取综合报告样式
     */
    private String getComprehensiveReportStyles() {
        return getAbnormalReportStyles() + """
            
            /* 综合报告额外样式 */
            .financial-overview-section {
                background: linear-gradient(135deg, #2b6cb0 0%, #4299e1 100%);
                color: white;
                padding: 25px;
                border-radius: 10px;
                margin-bottom: 30px;
            }
            
            .financial-overview-section h2 {
                color: white;
                text-align: center;
                margin-bottom: 20px;
            }
            
            .abnormal-section {
                background: linear-gradient(135deg, #e53e3e 0%, #fc8181 100%);
                color: white;
                padding: 25px;
                border-radius: 10px;
                margin-bottom: 30px;
            }
            
            .abnormal-section h2 {
                color: white;
                text-align: center;
                margin-bottom: 20px;
            }
            
            .section {
                margin-bottom: 30px;
                padding: 20px;
                border: 1px solid #e2e8f0;
                border-radius: 8px;
                background: #f7fafc;
            }
            
            .section h2 {
                color: #2d3748;
                font-size: 20px;
                margin-bottom: 15px;
                border-bottom: 2px solid #4299e1;
                padding-bottom: 5px;
            }
            
            .abnormal-detail-section h2 {
                border-bottom: 2px solid #e53e3e;
            }
            """;
    }

    // ==================== HTML内容生成方法 ====================

    /**
     * 生成综合异动报告HTML内容（网页版，优化样式）
     */
    private String generateComprehensiveAbnormalReportHtmlContent(Long userId, String stockCode,
                                                                 StockRealTimeInfoSingleResponse stockData,
                                                                 StockAnalysisResult analysisResult, AlertConfig alertConfig,
                                                                 StockAnalysisReportDTO financialReport) {
        StringBuilder html = new StringBuilder();

        // 从股票数据中提取信息
        String stockName = extractStockName(stockData.data());
        BigDecimal currentPrice = extractCurrentPrice(stockData.data());

        // 从实体类中直接获取数据
        String abnormalType = analysisResult.getAbnormalType();
        BigDecimal changeRatio = analysisResult.getChangeRatio();
        BigDecimal lastRecordPrice = analysisResult.getLastRecordPrice();
        BigDecimal triggerThreshold = analysisResult.getTriggerThreshold();

        // 优先使用分析结果中的数据
        if (StringUtils.hasText(analysisResult.getStockName())) {
            stockName = analysisResult.getStockName();
        }
        if (analysisResult.getCurrentPrice() != null) {
            currentPrice = analysisResult.getCurrentPrice();
        }

        // 如果财务报告中有股票名称，优先使用
        if (financialReport != null && StringUtils.hasText(financialReport.getStockName())) {
            stockName = financialReport.getStockName();
        }

        // HTML头部和样式（网页优化版）
        html.append("<!DOCTYPE html>")
            .append("<html lang=\"zh-CN\">")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">")
            .append("<title>股票异动综合分析报告 - ").append(stockCode).append("</title>")
            .append("<style>")
            .append(getWebOptimizedStyles())
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 报告标题
        html.append("<div class=\"header\">")
            .append("<h1>📊 股票异动综合分析报告</h1>")
            .append("<div class=\"stock-info\">")
            .append("<span class=\"stock-code\">").append(stockCode).append("</span>");

        if (StringUtils.hasText(stockName)) {
            html.append("<span class=\"stock-name\">").append(stockName).append("</span>");
        }

        html.append("</div>")
            .append("<div class=\"report-time\">📅 报告时间: ")
            .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</div>")
            .append("</div>");

        // 第一部分：异动概述
        html.append("<div class=\"section abnormal-section\">")
            .append("<h2>🚨 异动概述</h2>")
            .append("<div class=\"summary-grid\">");

        // 异动信息卡片
        if (StringUtils.hasText(abnormalType)) {
            String typeClass = getAbnormalTypeClass(abnormalType);
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">异动类型</div>")
                .append("<div class=\"card-value ").append(typeClass).append("\">")
                .append(abnormalType).append("</div>")
                .append("</div>");
        }

        if (currentPrice != null) {
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">当前价格</div>")
                .append("<div class=\"card-value price\">¥").append(currentPrice).append("</div>")
                .append("</div>");
        }

        if (changeRatio != null) {
            String ratioClass = changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative";
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">涨跌幅</div>")
                .append("<div class=\"card-value ").append(ratioClass).append("\">")
                .append(changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "")
                .append(changeRatio).append("%</div>")
                .append("</div>");
        }

        if (triggerThreshold != null) {
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">触发阈值</div>")
                .append("<div class=\"card-value threshold\">").append(triggerThreshold).append("%</div>")
                .append("</div>");
        }

        html.append("</div>")
            .append("</div>");

        // 第二部分：财务分析概览（如果有的话）
        if (financialReport != null) {
            html.append("<div class=\"section financial-overview-section\">")
                .append("<h2>📈 财务健康度概览</h2>")
                .append("<div class=\"summary-grid\">");

            if (financialReport.getOverallScore() != null) {
                html.append("<div class=\"summary-card\">")
                    .append("<div class=\"card-title\">综合评分</div>")
                    .append("<div class=\"card-value score\">").append(financialReport.getOverallScore()).append("/100分</div>")
                    .append("</div>");
            }

            if (financialReport.getRiskLevel() != null) {
                String riskClass = getRiskLevelClass(financialReport.getRiskLevel());
                html.append("<div class=\"summary-card\">")
                    .append("<div class=\"card-title\">风险等级</div>")
                    .append("<div class=\"card-value ").append(riskClass).append("\">")
                    .append(financialReport.getRiskLevel()).append("级</div>")
                    .append("</div>");
            }

            if (StringUtils.hasText(financialReport.getInvestmentRecommendation())) {
                String recommendClass = getRecommendationClass(financialReport.getInvestmentRecommendation());
                html.append("<div class=\"summary-card\">")
                    .append("<div class=\"card-title\">投资建议</div>")
                    .append("<div class=\"card-value ").append(recommendClass).append("\">")
                    .append(financialReport.getInvestmentRecommendation()).append("</div>")
                    .append("</div>");
            }

            html.append("</div>");

            // 建议理由
            if (StringUtils.hasText(financialReport.getRecommendationReason())) {
                html.append("<div class=\"recommendation-reason\">")
                    .append("<h3>💡 投资建议理由</h3>")
                    .append("<p>").append(financialReport.getRecommendationReason()).append("</p>")
                    .append("</div>");
            }

            html.append("</div>");

            // 第三部分：详细财务分析
            addWebFinancialAnalysisSection(html, "💰 综合财务分析", financialReport.getFinancialAnalysis());
            addWebFinancialAnalysisSection(html, "📈 盈利能力分析", financialReport.getProfitabilityAnalysis());
            addWebFinancialAnalysisSection(html, "🛡️ 偿债能力分析", financialReport.getSolvencyAnalysis());
            addWebFinancialAnalysisSection(html, "⚙️ 营运能力分析", financialReport.getOperationalAnalysis());
            addWebFinancialAnalysisSection(html, "🚀 成长能力分析", financialReport.getGrowthAnalysis());
            addWebFinancialAnalysisSection(html, "💧 现金流分析", financialReport.getCashFlowAnalysis());
            addWebFinancialAnalysisSection(html, "📊 研报分析", financialReport.getResearchAnalysis());

            // AI总结
            if (StringUtils.hasText(financialReport.getAiSummary())) {
                html.append("<div class=\"section ai-summary-section\">")
                    .append("<h2>🤖 AI智能总结</h2>")
                    .append("<div class=\"ai-summary-content\">")
                    .append(formatWebAnalysisContent(financialReport.getAiSummary()))
                    .append("</div>")
                    .append("</div>");
            }
        }

        // 第四部分：异动详情
        html.append("<div class=\"section abnormal-detail-section\">")
            .append("<h2>💰 异动价格详情</h2>")
            .append("<div class=\"price-table\">")
            .append("<table>")
            .append("<thead><tr><th>项目</th><th>数值</th></tr></thead>")
            .append("<tbody>");

        if (lastRecordPrice != null) {
            html.append("<tr><td>上次记录价格</td><td>¥").append(lastRecordPrice).append("</td></tr>");
        }
        if (currentPrice != null) {
            html.append("<tr><td>当前价格</td><td>¥").append(currentPrice).append("</td></tr>");
        }
        if (changeRatio != null) {
            String changeText = changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "上涨" : "下跌";
            html.append("<tr><td>价格变化</td><td class=\"")
                .append(changeRatio.compareTo(BigDecimal.ZERO) >= 0 ? "positive" : "negative")
                .append("\">").append(changeText).append(" ").append(changeRatio.abs()).append("%</td></tr>");
        }

        html.append("</tbody></table>")
            .append("</div>")
            .append("</div>");

        // 第五部分：预警配置信息
        if (alertConfig != null) {
            html.append("<div class=\"section alert-config-section\">")
                .append("<h2>⚙️ 预警配置</h2>")
                .append("<div class=\"config-content\">")
                .append(formatWebAlertConfig(alertConfig))
                .append("</div>")
                .append("</div>");
        }

        // 第六部分：股票详细信息（如果有的话）
        if (stockData != null && stockData.data() != null && !stockData.data().isEmpty()) {
            html.append("<div class=\"section stock-detail-section\">")
                .append("<h2>📊 股票详细信息</h2>")
                .append("<div class=\"stock-table\">")
                .append(formatWebStockData(stockData.data()))
                .append("</div>")
                .append("</div>");
        }

        // 风险提示
        html.append("<div class=\"section risk-section\">")
            .append("<h2>⚠️ 风险提示</h2>")
            .append("<div class=\"risk-content\">")
            .append("<div class=\"risk-item\">")
            .append("<strong>🔍 异动说明：</strong> 股票价格变化超过预设阈值，触发异动预警。")
            .append("</div>")
            .append("<div class=\"risk-item\">")
            .append("<strong>📊 财务分析：</strong> 本报告结合了实时异动监测和深度财务分析，提供全面的投资参考。")
            .append("</div>")
            .append("<div class=\"risk-item\">")
            .append("<strong>⚠️ 投资风险：</strong> 股价异动可能由多种因素引起，财务数据具有滞后性，投资者应谨慎决策。")
            .append("</div>")
            .append("<div class=\"risk-item\">")
            .append("<strong>📋 数据来源：</strong> 本报告基于实时股票数据和公开财务报表数据生成，仅供参考。")
            .append("</div>");

        if (financialReport != null && StringUtils.hasText(financialReport.getRiskDescription())) {
            html.append("<div class=\"risk-item\">")
                .append("<strong>🎯 风险评级说明：</strong> ").append(financialReport.getRiskDescription())
                .append("</div>");
        }

        html.append("</div>")
            .append("</div>");

        // 页脚
        html.append("<div class=\"footer\">")
            .append("<div class=\"footer-content\">")
            .append("<p><strong>📢 免责声明：</strong> 本综合分析报告仅供参考，不构成投资建议。投资者应基于自身情况做出独立判断。</p>")
            .append("<p class=\"footer-meta\">")
            .append("👤 用户ID: ").append(userId).append(" | ")
            .append("⏰ 报告生成时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</p>")
            .append("</div>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 生成基础异动报告HTML内容
     */
    private String generateAbnormalReportHtmlContent(Long userId, String stockCode,
                                                    StockRealTimeInfoSingleResponse stockData,
                                                    StockAnalysisResult analysisResult, AlertConfig alertConfig) {
        // 复用综合报告方法，但不传入财务报告
        return generateComprehensiveAbnormalReportHtmlContent(userId, stockCode, stockData, analysisResult, alertConfig, null);
    }

    /**
     * 生成财务分析报告HTML内容
     */
    private String generateFinancialAnalysisHtmlContent(Long userId, StockAnalysisReportDTO analysisReport) {
        StringBuilder html = new StringBuilder();

        // HTML头部和样式
        html.append("<!DOCTYPE html>")
            .append("<html lang=\"zh-CN\">")
            .append("<head>")
            .append("<meta charset=\"UTF-8\">")
            .append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">")
            .append("<title>股票财务分析报告 - ").append(analysisReport.getStockCode()).append("</title>")
            .append("<style>")
            .append(getWebOptimizedStyles())
            .append("</style>")
            .append("</head>")
            .append("<body>");

        // 报告标题
        html.append("<div class=\"header\">")
            .append("<h1>📊 股票财务分析报告</h1>")
            .append("<div class=\"stock-info\">")
            .append("<span class=\"stock-code\">").append(analysisReport.getStockCode()).append("</span>");

        if (StringUtils.hasText(analysisReport.getStockName())) {
            html.append("<span class=\"stock-name\">").append(analysisReport.getStockName()).append("</span>");
        }

        html.append("</div>")
            .append("<div class=\"report-time\">📅 分析时间: ")
            .append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</div>")
            .append("</div>");

        // 核心结论概述
        html.append("<div class=\"section financial-overview-section\">")
            .append("<h2>🎯 核心结论</h2>")
            .append("<div class=\"summary-grid\">");

        if (analysisReport.getOverallScore() != null) {
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">综合评分</div>")
                .append("<div class=\"card-value score\">").append(analysisReport.getOverallScore()).append("/100分</div>")
                .append("</div>");
        }

        if (analysisReport.getRiskLevel() != null) {
            String riskClass = getRiskLevelClass(analysisReport.getRiskLevel());
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">风险等级</div>")
                .append("<div class=\"card-value ").append(riskClass).append("\">")
                .append(analysisReport.getRiskLevel()).append("级</div>")
                .append("</div>");
        }

        if (StringUtils.hasText(analysisReport.getInvestmentRecommendation())) {
            String recommendClass = getRecommendationClass(analysisReport.getInvestmentRecommendation());
            html.append("<div class=\"summary-card\">")
                .append("<div class=\"card-title\">投资建议</div>")
                .append("<div class=\"card-value ").append(recommendClass).append("\">")
                .append(analysisReport.getInvestmentRecommendation()).append("</div>")
                .append("</div>");
        }

        html.append("</div>");

        // 建议理由
        if (StringUtils.hasText(analysisReport.getRecommendationReason())) {
            html.append("<div class=\"recommendation-reason\">")
                .append("<h3>💡 建议理由</h3>")
                .append("<p>").append(analysisReport.getRecommendationReason()).append("</p>")
                .append("</div>");
        }

        html.append("</div>");

        // 财务分析各个维度
        addWebFinancialAnalysisSection(html, "💰 综合财务分析", analysisReport.getFinancialAnalysis());
        addWebFinancialAnalysisSection(html, "📈 盈利能力分析", analysisReport.getProfitabilityAnalysis());
        addWebFinancialAnalysisSection(html, "🛡️ 偿债能力分析", analysisReport.getSolvencyAnalysis());
        addWebFinancialAnalysisSection(html, "⚙️ 营运能力分析", analysisReport.getOperationalAnalysis());
        addWebFinancialAnalysisSection(html, "🚀 成长能力分析", analysisReport.getGrowthAnalysis());
        addWebFinancialAnalysisSection(html, "💧 现金流分析", analysisReport.getCashFlowAnalysis());
        addWebFinancialAnalysisSection(html, "📊 研报分析", analysisReport.getResearchAnalysis());

        // 目标价格区间
        if (StringUtils.hasText(analysisReport.getTargetPriceRange())) {
            html.append("<div class=\"section target-price-section\">")
                .append("<h2>🎯 目标价格区间</h2>")
                .append("<div class=\"target-price-content\">")
                .append(formatWebAnalysisContent(analysisReport.getTargetPriceRange()))
                .append("</div>")
                .append("</div>");
        }

        // AI总结
        if (StringUtils.hasText(analysisReport.getAiSummary())) {
            html.append("<div class=\"section ai-summary-section\">")
                .append("<h2>🤖 AI智能总结</h2>")
                .append("<div class=\"ai-summary-content\">")
                .append(formatWebAnalysisContent(analysisReport.getAiSummary()))
                .append("</div>")
                .append("</div>");
        }

        // 风险提示
        html.append("<div class=\"section risk-section\">")
            .append("<h2>⚠️ 风险提示</h2>")
            .append("<div class=\"risk-content\">")
            .append("<div class=\"risk-item\">")
            .append("<strong>📋 数据来源：</strong> 本报告基于公开财务报表数据生成，数据时效性可能存在滞后。")
            .append("</div>")
            .append("<div class=\"risk-item\">")
            .append("<strong>🔍 分析局限：</strong> 财务分析仅基于历史数据，无法预测未来市场变化和公司表现。")
            .append("</div>")
            .append("<div class=\"risk-item\">")
            .append("<strong>⚠️ 投资风险：</strong> 股票投资存在风险，过往业绩不代表未来表现，请谨慎决策。")
            .append("</div>");

        if (StringUtils.hasText(analysisReport.getRiskDescription())) {
            html.append("<div class=\"risk-item\">")
                .append("<strong>🎯 风险评级说明：</strong> ").append(analysisReport.getRiskDescription())
                .append("</div>");
        }

        html.append("</div>")
            .append("</div>");

        // 页脚
        html.append("<div class=\"footer\">")
            .append("<div class=\"footer-content\">")
            .append("<p><strong>📢 免责声明：</strong> 本财务分析报告仅供参考，不构成投资建议。投资者应基于自身情况做出独立判断。</p>")
            .append("<p class=\"footer-meta\">")
            .append("👤 用户ID: ").append(userId).append(" | ")
            .append("⏰ 报告生成时间: ").append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
            .append("</p>")
            .append("</div>")
            .append("</div>");

        html.append("</body></html>");

        return html.toString();
    }

    /**
     * 生成错误页面HTML
     */
    private String generateErrorHtml(Long userId, String stockCode, String errorMessage) {
        String template = """
            <!DOCTYPE html>
            <html lang="zh-CN">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>报告生成错误</title>
                <style>
                    body { 
                        font-family: sans-serif; 
                        margin: 40px; 
                        background: #f5f5f5; 
                        color: #333;
                    }
                    .error-container {
                        background: white;
                        padding: 30px;
                        border-radius: 10px;
                        box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                        max-width: 600px;
                        margin: 0 auto;
                    }
                    .error-icon { 
                        text-align: center; 
                        font-size: 48px; 
                        color: #f44336; 
                        margin-bottom: 20px;
                    }
                    .error-title { 
                        text-align: center; 
                        color: #f44336; 
                        margin-bottom: 20px;
                    }
                    .error-message {
                        background: #ffebee;
                        border: 1px solid #ffcdd2;
                        padding: 15px;
                        border-radius: 5px;
                        margin: 20px 0;
                    }
                    .error-info {
                        background: #f5f5f5;
                        padding: 15px;
                        border-radius: 5px;
                        margin: 20px 0;
                        font-size: 14px;
                        color: #666;
                    }
                </style>
            </head>
            <body>
                <div class="error-container">
                    <div class="error-icon">❌</div>
                    <h1 class="error-title">报告生成失败</h1>
                    <div class="error-message">
                        <strong>错误信息：</strong> %s
                    </div>
                    <div class="error-info">
                        <p><strong>股票代码：</strong> %s</p>
                        <p><strong>用户ID：</strong> %s</p>
                        <p><strong>时间：</strong> %s</p>
                    </div>
                    <p><strong>建议：</strong> 请稍后重试或联系系统管理员。</p>
                </div>
            </body>
            </html>
            """;
        
        return String.format(template, 
            errorMessage != null ? errorMessage : "未知错误",
            stockCode != null ? stockCode : "未知",
            userId != null ? userId.toString() : "未知",
            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }

    // ==================== Web版本辅助方法 ====================

    /**
     * 添加网页版财务分析章节
     */
    private void addWebFinancialAnalysisSection(StringBuilder html, String title, String content) {
        if (StringUtils.hasText(content)) {
            html.append("<div class=\"section analysis-section\">")
                .append("<h2>").append(title).append("</h2>")
                .append("<div class=\"analysis-content\">")
                .append(formatWebAnalysisContent(content))
                .append("</div>")
                .append("</div>");
        }
    }

    /**
     * 格式化网页版分析内容
     */
    private String formatWebAnalysisContent(String content) {
        if (!StringUtils.hasText(content)) {
            return "";
        }

        // 更丰富的markdown到HTML转换
        return content
            .replaceAll("\\*\\*([^*]+)\\*\\*", "<strong>$1</strong>") // 粗体
            .replaceAll("\\*([^*]+)\\*", "<em>$1</em>") // 斜体
            .replaceAll("\\n\\n", "</p><p>") // 段落分隔
            .replaceAll("\\n", "<br/>") // 换行
            .replaceAll("^", "<p>") // 开始段落
            .replaceAll("$", "</p>"); // 结束段落
    }

    /**
     * 格式化网页版预警配置
     */
    private String formatWebAlertConfig(AlertConfig alertConfig) {
        StringBuilder config = new StringBuilder();

        config.append("<table>")
              .append("<thead><tr><th>配置项</th><th>数值</th></tr></thead>")
              .append("<tbody>");

        BigDecimal riseRatio = alertConfig.getRiseRatio();
        BigDecimal fallRatio = alertConfig.getFallRatio();
        Integer pushFrequency = alertConfig.getPushFrequency();

        if (riseRatio != null) {
            config.append("<tr><td>上涨预警阈值</td><td class=\"positive\">").append(riseRatio).append("%</td></tr>");
        }
        if (fallRatio != null) {
            config.append("<tr><td>下跌预警阈值</td><td class=\"negative\">").append(fallRatio).append("%</td></tr>");
        }
        if (pushFrequency != null) {
            config.append("<tr><td>推送频率</td><td>").append(pushFrequency).append("</td></tr>");
        }

        config.append("</tbody></table>");

        return config.toString();
    }

    /**
     * 格式化网页版股票数据
     */
    private String formatWebStockData(List<StockRealTimeInfo> stockDataList) {
        StringBuilder table = new StringBuilder();
        table.append("<table>")
             .append("<thead><tr><th>项目</th><th>数值</th></tr></thead>")
             .append("<tbody>");

        for (StockRealTimeInfo info : stockDataList) {
            table.append("<tr>")
                 .append("<td>").append(info.item()).append("</td>")
                 .append("<td>").append(info.value()).append("</td>")
                 .append("</tr>");
        }

        table.append("</tbody></table>");
        return table.toString();
    }

    /**
     * 获取网页优化样式
     */
    private String getWebOptimizedStyles() {
        return """
            * {
                margin: 0;
                padding: 0;
                box-sizing: border-box;
            }
            
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
                line-height: 1.6;
                color: #333;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                min-height: 100vh;
                padding: 20px;
            }
            
            .header {
                background: white;
                text-align: center;
                margin-bottom: 30px;
                padding: 30px;
                border-radius: 15px;
                box-shadow: 0 8px 32px rgba(0,0,0,0.1);
            }
            
            .header h1 {
                color: #2c3e50;
                font-size: 32px;
                margin-bottom: 15px;
                font-weight: 700;
            }
            
            .stock-info {
                margin: 15px 0;
            }
            
            .stock-code {
                font-size: 24px;
                font-weight: bold;
                color: #e74c3c;
                margin-right: 15px;
                background: #ffebee;
                padding: 8px 16px;
                border-radius: 20px;
                display: inline-block;
            }
            
            .stock-name {
                font-size: 20px;
                color: #34495e;
                font-weight: 500;
            }
            
            .report-time {
                color: #7f8c8d;
                font-size: 16px;
                margin-top: 10px;
            }
            
            .section {
                background: white;
                margin-bottom: 25px;
                padding: 25px;
                border-radius: 15px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.08);
                transition: transform 0.2s ease, box-shadow 0.2s ease;
            }
            
            .section:hover {
                transform: translateY(-2px);
                box-shadow: 0 8px 30px rgba(0,0,0,0.12);
            }
            
            .section h2 {
                color: #2c3e50;
                font-size: 24px;
                margin-bottom: 20px;
                border-bottom: 3px solid #3498db;
                padding-bottom: 10px;
                font-weight: 600;
            }
            
            .abnormal-section {
                background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
                color: white;
            }
            
            .abnormal-section h2 {
                color: white;
                border-bottom: 3px solid rgba(255,255,255,0.3);
            }
            
            .financial-overview-section {
                background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%);
                color: white;
            }
            
            .financial-overview-section h2 {
                color: white;
                border-bottom: 3px solid rgba(255,255,255,0.3);
            }
            
            .summary-grid {
                display: grid;
                grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                gap: 20px;
                margin-top: 20px;
            }
            
            .summary-card {
                background: rgba(255,255,255,0.1);
                padding: 20px;
                border-radius: 10px;
                text-align: center;
                backdrop-filter: blur(10px);
                border: 1px solid rgba(255,255,255,0.2);
            }
            
            .abnormal-section .summary-card,
            .financial-overview-section .summary-card {
                background: rgba(255,255,255,0.15);
            }
            
            .section:not(.abnormal-section):not(.financial-overview-section) .summary-card {
                background: #f8f9fa;
                border: 1px solid #e9ecef;
            }
            
            .card-title {
                font-size: 14px;
                opacity: 0.8;
                margin-bottom: 8px;
                font-weight: 500;
            }
            
            .card-value {
                font-size: 20px;
                font-weight: bold;
            }
            
            .positive {
                color: #27ae60 !important;
            }
            
            .negative {
                color: #e74c3c !important;
            }
            
            .price {
                color: #3498db !important;
            }
            
            .threshold {
                color: #f39c12 !important;
            }
            
            .score {
                color: #f1c40f !important;
            }
            
            .risk-low {
                color: #27ae60 !important;
            }
            
            .risk-medium {
                color: #f39c12 !important;
            }
            
            .risk-high {
                color: #e74c3c !important;
            }
            
            .recommend-buy {
                color: #27ae60 !important;
                background: rgba(39, 174, 96, 0.1);
                padding: 4px 12px;
                border-radius: 15px;
            }
            
            .recommend-sell {
                color: #e74c3c !important;
                background: rgba(231, 76, 60, 0.1);
                padding: 4px 12px;
                border-radius: 15px;
            }
            
            .recommend-hold {
                color: #f39c12 !important;
                background: rgba(243, 156, 18, 0.1);
                padding: 4px 12px;
                border-radius: 15px;
            }
            
            .type-rise {
                color: #27ae60 !important;
                background: rgba(39, 174, 96, 0.1);
                padding: 4px 12px;
                border-radius: 15px;
            }
            
            .type-fall {
                color: #e74c3c !important;
                background: rgba(231, 76, 60, 0.1);
                padding: 4px 12px;
                border-radius: 15px;
            }
            
            .recommendation-reason {
                margin-top: 20px;
                padding: 20px;
                background: rgba(255,255,255,0.1);
                border-radius: 10px;
                backdrop-filter: blur(10px);
            }
            
            .recommendation-reason h3 {
                margin-bottom: 10px;
                font-size: 18px;
            }
            
            .analysis-content {
                line-height: 1.8;
                font-size: 16px;
            }
            
            .analysis-content p {
                margin-bottom: 15px;
            }
            
            .analysis-content strong {
                color: #2c3e50;
                font-weight: 600;
            }
            
            table {
                width: 100%;
                border-collapse: collapse;
                margin: 20px 0;
                background: white;
                border-radius: 10px;
                overflow: hidden;
                box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            }
            
            th, td {
                padding: 15px;
                text-align: left;
                border-bottom: 1px solid #e9ecef;
            }
            
            th {
                background: #f8f9fa;
                font-weight: 600;
                color: #2c3e50;
                font-size: 14px;
                text-transform: uppercase;
                letter-spacing: 0.5px;
            }
            
            tr:hover {
                background: #f8f9fa;
            }
            
            .risk-section {
                background: linear-gradient(135deg, #ffeaa7 0%, #fab1a0 100%);
                border: none;
            }
            
            .risk-section h2 {
                color: #2d3436;
                border-bottom: 3px solid #fdcb6e;
            }
            
            .risk-content {
                color: #2d3436;
            }
            
            .risk-item {
                margin-bottom: 15px;
                padding: 15px;
                background: rgba(255,255,255,0.3);
                border-radius: 8px;
                backdrop-filter: blur(5px);
            }
            
            .ai-summary-section {
                background: linear-gradient(135deg, #a29bfe 0%, #6c5ce7 100%);
                color: white;
            }
            
            .ai-summary-section h2 {
                color: white;
                border-bottom: 3px solid rgba(255,255,255,0.3);
            }
            
            .footer {
                background: #2c3e50;
                color: white;
                margin-top: 40px;
                padding: 30px;
                border-radius: 15px;
                text-align: center;
            }
            
            .footer-content p {
                margin-bottom: 10px;
                line-height: 1.6;
            }
            
            .footer-meta {
                font-size: 14px;
                opacity: 0.8;
                margin-top: 15px !important;
            }
            
            @media (max-width: 768px) {
                body {
                    padding: 10px;
                }
                
                .header h1 {
                    font-size: 24px;
                }
                
                .stock-code {
                    font-size: 18px;
                    display: block;
                    margin-bottom: 10px;
                }
                
                .stock-name {
                    font-size: 16px;
                }
                
                .summary-grid {
                    grid-template-columns: 1fr;
                }
                
                .section {
                    padding: 15px;
                }
                
                .section h2 {
                    font-size: 20px;
                }
                
                table {
                    font-size: 14px;
                }
                
                th, td {
                    padding: 10px;
                }
            }
            """;
    }
}
